package ch.fhnw.qualiscan.api;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import ch.fhnw.qualiscan.application.models.ApiModel;
import ch.fhnw.qualiscan.application.models.DomainModel;
import ch.fhnw.qualiscan.application.models.RoleModel;
import ch.fhnw.qualiscan.application.models.SurveyModel;
import ch.fhnw.qualiscan.application.models.UserModel;
import ch.fhnw.qualiscan.core.db.HibernateSession;
import ch.fhnw.qualiscan.core.db.pojos.Answer;
import ch.fhnw.qualiscan.core.db.pojos.Confidence;
import ch.fhnw.qualiscan.core.db.pojos.Domain;
import ch.fhnw.qualiscan.core.db.pojos.Language;
import ch.fhnw.qualiscan.core.db.pojos.Question;
import ch.fhnw.qualiscan.core.db.pojos.Role;
import ch.fhnw.qualiscan.core.db.pojos.Survey;
import ch.fhnw.qualiscan.core.db.pojos.SurveyUserRole;
import ch.fhnw.qualiscan.core.db.pojos.User;
import ch.fhnw.qualiscan.core.helpers.UserSession;

/**
 * Servlet implementation class FlashAPI
 */
public class FlashAPI extends HttpServlet {
	private static final long serialVersionUID = 1L;

	private RoleModel roleModel;
	private SurveyModel surveyModel;
	private UserModel userModel;
	private DomainModel domainModel;
	private UserSession userSession;
	private Survey survey;
	private SurveyUserRole sur;
	private Domain domain;
	private Question question;
	private Role role;
	private HibernateSession hibernateSession;
	private ApiModel apiModel;
	private List<Answer> answerList;
	private List<Answer> answerListArray[];
	private Language language;
	private PrintWriter pw;
	private int chartType;
	private int personal;
	private User user;
	private ArrayList<Role> roleList;
	
	private int nDisagree;
	private int nDisagreeArray[];
	private int nPartDisagree;
	private int nPartDisagreeArray[];
	private int nPartAgree;
	private int nPartAgreeArray[];
	private int nAgree;
	private int nAgreeArray[];
	private int nNotApl;
	private int nNotAplArray[];
	private int sum;
	private int sumArray[];
	private double average;
	private double personalAverage;
	private double averageArray[];
	private int confidenceArray[];
	int personalConfidence;
	
    /**
     * Default constructor. 
     */
    public FlashAPI() {
    	roleModel = new RoleModel();
    	userModel = new UserModel();
    	domainModel = new DomainModel();
    	surveyModel = new SurveyModel();
    	hibernateSession = new HibernateSession();
    	apiModel = new ApiModel();
    	userSession = new UserSession();
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//URL ?charttype=0/1&language=langID&survey=surveyID&domain=domainID&question=questionID&role=roleID&user=userID
		response.setContentType("application/json");
		pw = new PrintWriter(response.getOutputStream());
		
		survey = null;
		
		if(!request.getParameter("survey").equals("")) {
			survey = surveyModel.getSurveyById(Integer.valueOf(request.getParameter("survey")).intValue());
		}
		
		roleList = roleModel.getRoles(survey);
		
		nDisagree = 0;
		nDisagreeArray = new int[roleList.size()];
    	nPartDisagree = 0;
    	nPartDisagreeArray = new int[roleList.size()];
    	nPartAgree = 0;
    	nPartAgreeArray = new int[roleList.size()];
    	nAgree = 0;
    	nAgreeArray = new int[roleList.size()];
    	nNotApl = 0;
    	nNotAplArray = new int[roleList.size()];
    	sum = 0;
    	sumArray = new int[roleList.size()];
    	average = 0;
    	averageArray = new double[roleList.size()];
    	personal = 0;
    	question = null;
    	domain = null;
    	chartType = 0;
    	personalAverage = 0;
    	answerList = new ArrayList<Answer>();
    	confidenceArray = new int[roleList.size()];
    	personalConfidence = 0;
    	answerListArray = (List<Answer>[]) new List[roleList.size()];
    
		
    	if(!request.getParameter("user").equals("")) {
			user = userModel.getUserById(Integer.valueOf(request.getParameter("user")).intValue());
		}
		
    	
		
		language = new Language();
		
		language.setId(Integer.valueOf(request.getParameter("language")).intValue());
		
		chartType = Integer.valueOf(request.getParameter("charttype")).intValue();
		
		
		if(!request.getParameter("domain").equals("")) {
			domain = (Domain) hibernateSession.getSession().get(Domain.class, Integer.valueOf(request.getParameter("domain")).intValue());
		}
		
		if(!request.getParameter("sur").equals("")) {
			sur = (SurveyUserRole) hibernateSession.getSession().get(SurveyUserRole.class, Integer.valueOf(request.getParameter("sur")).intValue());
		}
		
		if(!request.getParameter("question").equals("")) {
			question = (Question) hibernateSession.getSession().get(Question.class, Integer.valueOf(request.getParameter("question")).intValue());
		}
		if(!request.getParameter("role").equals("")) {
			role = (Role) hibernateSession.getSession().get(Role.class, Integer.valueOf(request.getParameter("role")).intValue());
		}
		
		if (domain != null) {
			//Small Chart
			if (chartType == 0) {
				if (role == null) {
					answerList = apiModel.getAnswersForDomain(survey, domain);
				}
				else {
					answerList = apiModel.getAnswersForDomain(survey, domain, role);
				}
			}
			//Big Chart
			else {
				for (int r = 0; r < roleList.size(); r++) {
					answerListArray[r] = apiModel.getAnswersForDomain(survey, domain, roleList.get(r));
				}
				//Personal Data
				List<Answer> personalAnswerList = apiModel.getAnswersForDomain(sur, domain);

				int nPersonalDisagree = 0;
				int nPersonalPartDisagree = 0;
				int nPersonalPartAgree = 0;
				int nPersonalAgree = 0;
				int personalSum = 0;
				for(int i = 0; i < personalAnswerList.size(); i++) {
					if (personalAnswerList.get(i).getAnswer() == 1) {
						nPersonalDisagree++;
					}
					if (personalAnswerList.get(i).getAnswer() == 2) {
						nPersonalPartDisagree++;
					}
					if(personalAnswerList.get(i).getAnswer() == 3) {
						nPersonalPartAgree++;
					}
					if(personalAnswerList.get(i).getAnswer() == 4) {
						nPersonalAgree++;
					}
					
					personalSum++;
				}
				if (personalSum != 0) {
					personalAverage = (0.5*nPersonalDisagree + 1.5*nPersonalPartDisagree + 2.5*nPersonalPartAgree + 3.5*nPersonalAgree) / personalSum;
				}
			}
		}
		
		if (question != null) {
			//Small Chart
			if (chartType == 0) {
				if (role == null) {
					answerList = apiModel.getAnswersForQuestion(survey, question);
				}
				else {
					answerList = apiModel.getAnswersForQuestion(survey, question, role);
				}
				//Get the domain for of the answer (is else no available because not in the url)
				if (answerList.size() > 0) {
					domain = answerList.get(0).getDomain();
				}
				
			}
			//Big Chart
			else {
				for (int r = 0; r < roleList.size(); r++) {
					answerListArray[r] = apiModel.getAnswersForQuestion(survey, question, roleList.get(r));
				}
				
				//Get the domain for of the answer (is else not available because not in the url)
				if (answerListArray.length > 0) {
					if (answerListArray[0].size() > 0) {
						domain = answerListArray[0].get(0).getDomain();
					}
				}
	
				Answer answer = apiModel.getAnswersForQuestion(sur, question);
				if (answer != null) {
					personalAverage = answer.getAnswer()-1;
				}
				
			}	
		}

		//Small Chart
		if (chartType == 0) {
			for (int i = 0; i < answerList.size(); i++) {
				if (answerList.get(i).getAnswer() == 1) {
					nDisagree++;
				}
				if (answerList.get(i).getAnswer() == 2) {
					nPartDisagree++;
				}
				if(answerList.get(i).getAnswer() == 3) {
					nPartAgree++;
				}
				if(answerList.get(i).getAnswer() == 4) {
					nAgree++;
				}
				if(answerList.get(i).getAnswer() == 5) {
					nNotApl++;
				}
				
				sum++;
			}
		}
		//Big Chart
		else  {
			for (int r = 0; r < roleList.size(); r++) {
				for (int i = 0; i < answerListArray[r].size(); i++) {
					if (answerListArray[r].get(i).getAnswer() == 1) {
						nDisagreeArray[r]++;
					}
					if (answerListArray[r].get(i).getAnswer() == 2) {
						nPartDisagreeArray[r]++;
					}
					if(answerListArray[r].get(i).getAnswer() == 3) {
						nPartAgreeArray[r]++;
					}
					if(answerListArray[r].get(i).getAnswer() == 4) {
						nAgreeArray[r]++;
					}
					if(answerListArray[r].get(i).getAnswer() == 5) {
						nNotAplArray[r]++;
					}
					
					sumArray[r]++;
				}
				confidenceArray[r] = domainModel.getAverageConfidenceForDomain(domain, survey, roleList.get(r));

				if (sumArray[r] == 0) {
					averageArray[r] = 0;
				}
				else {
					averageArray[r] = (0.5*nDisagreeArray[r] + 1.5*nPartDisagreeArray[r] + 2.5*nPartAgreeArray[r] + 3.5*nAgreeArray[r]) / sumArray[r];
				}
			}
			
			if (user != null && domain != null) {
				Confidence confidence = domainModel.getConfidenceOfDomain(sur, domain);
				if(confidence != null) {
					personalConfidence = confidence.getConfidence();
				}
				
			}
			
			
		}

		buildJSON(request, response);
	}
	
	public void buildJSON(HttpServletRequest request, HttpServletResponse response) {
		
		
		JSONObject json = new JSONObject();
		
		JSONObject graphics = new JSONObject();
		
		JSONArray bgcolors = new JSONArray();
		bgcolors.put("0xDC3E18");
		bgcolors.put("0xF1D730");
		bgcolors.put("0xD1E5E8");
		bgcolors.put("0x4A45A7");
		bgcolors.put("0x808080");
		
		JSONArray gridcolors = new JSONArray();
		gridcolors.put("0x000000");
		gridcolors.put("0xcccccc");
		
		JSONArray pointcolors = new JSONArray();
		pointcolors.put("0x99cc00");
		pointcolors.put("0xff6600");
		
		JSONObject data = new JSONObject();
		
		JSONArray labels = new JSONArray();
		labels.put("Disagree");
		labels.put("Partially disagree");
		labels.put("Partially agree");
		labels.put("Agree");
		labels.put("Not applicable");
		
		JSONArray roles = new JSONArray();
		for (int r = 0; r < roleList.size(); r++) {
			roles.put(userModel.getRoleText(roleList.get(r), language).getTitle());
		}
		
		try {
			graphics.put("bgcolors", bgcolors);
			graphics.put("gridcolors", gridcolors);
			graphics.put("pointcolors", pointcolors);
		} catch (JSONException e1) {}
		
		try {
			data.put("labels", labels);
			data.put("roles", roles);
			String message = "";
			boolean noData = true;
			if (chartType == 1) {
				//Big Chart
				JSONArray dataArrayRole = new JSONArray();
				for (int r = 0; r < roleList.size(); r++) {
					JSONArray dataArray = new JSONArray();
					//Disagree
					dataArray.put(nDisagreeArray[r]);
					//Partially Disagree
					dataArray.put(nPartDisagreeArray[r]);
					//Partially Agree
					dataArray.put(nPartAgreeArray[r]);
					//Agree
					dataArray.put(nAgreeArray[r]);
					//Not Applicable
					dataArray.put(nNotAplArray[r]);
					//Sum
					dataArray.put(sumArray[r]);
					//Average
					dataArray.put(averageArray[r]);
					//Confidence
					dataArray.put(confidenceArray[r]);
					
					dataArrayRole.put(dataArray);
					
					if(sumArray[r] > 0) {
						noData = false;
					}
				}
				
				if (noData == true) {
					message = "No data";
				}
				data.put("data", dataArrayRole);
				
				//Personal
				JSONArray personalArray = new JSONArray();
				personalArray.put(personalAverage);
				personalArray.put(personalConfidence);
				
				data.put("personal", personalArray);
			}
			else if(chartType == 0) {
				JSONArray dataArray = new JSONArray();
				//Disagree
				dataArray.put(nDisagree);
				//Partially Disagree
				dataArray.put(nPartDisagree);
				//Partially Agree
				dataArray.put(nPartAgree);
				//Agree
				dataArray.put(nAgree);
				//Not Applicable
				dataArray.put(nNotApl);
				//Sum
				dataArray.put(sum);
				//Average
				double average = 0;
				if (sum != 0) {
					average = (0.5*nDisagree + 1.5*nPartDisagree + 2.5*nPartAgree + 3.5*nAgree) / sum;
				}
				dataArray.put(average);
				
				data.put("data", dataArray);
				if (sum == 0) {
					message = "No data";
				}
			}
			data.put("message", message);
			
		} catch (JSONException e1) {}
	
		
		try {
			
			json.put("graphics", graphics);
			json.put("data", data);
		} catch (JSONException e) {}
		
		pw.println(json.toString());
		
		pw.close();
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
	}

}
